﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;

namespace Accona.Remoting.Remoting
{
    public class MethodSerializer
    {
        private readonly Guid senderId;

        public MethodSerializer(Guid senderId)
        {
            this.senderId = senderId;
        }

        public byte[] SerializeMethodCall(MethodInfo methodInfo, object[] parameters, bool asynchronousCall, Guid callId,
                                          ServiceInfo availibleService)
        {
            IEnumerable<Type> types = from a in methodInfo.GetParameters() select a.ParameterType;

            var buffer = new byte[1400];
            var stream = new MemoryStream(buffer);
            var formatter = new BinaryFormatter();
            formatter.Serialize(stream, new MethodInvocationInfo
                                            {
                                                SourceMetaData = new MethodInvocationInfo.SourceInfo
                                                                     {
                                                                         ApplicationId = senderId,
                                                                         Name = "",
                                                                         CallId = callId,
                                                                         AsynchronousCall = asynchronousCall,
                                                                         TargetId = availibleService.ServerId
                                                                     },
                                                MethodName = methodInfo.Name,
                                                Type = methodInfo.DeclaringType,
                                                ParameterTypes =
                                                    methodInfo.GetParameters().Select(a => a.ParameterType).ToArray(),
                                                Parameters = parameters
                                            });
            return buffer;
        }

        public MethodInvocationInfo DeserializeMethodCall(byte[] data)
        {
            var stream = new MemoryStream(data);
            var formatter = new BinaryFormatter();
            object methodInfo = formatter.Deserialize(stream);
            return (MethodInvocationInfo) methodInfo;
        }
    }
}